﻿using System;
using System.Text;
using System.Collections.Generic;
using System.Linq;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using Foothill.Service.UserAccount;
using Moq;
using Foothill.DataAccess.Interface;
using Foothill.Model;
using Foothill.Service.Email;
using Foothill.Service.Validation;
using Foothill.Common.Logging;
using Foothill.Service.SystemMessage;
using Foothill.Service.Exceptions;
using Foothill.Service.Configuration;

namespace Foothill.Service.Test
{
    [TestClass]
    public class AccountRegistrationManagerTest
    {
        private AccountRegistrationManager _underTest;

        private Mock<IValidationService> _validationServiceMock;
        private Mock<IUserAccountRepo> _userAccountRepoMock;
        private Mock<IStringGenerator> _stringGeneratorMock;
        private Mock<IEmailSender> _emailSenderMock;
        private Mock<IHashUtility> _hashUtilityMock;
        private Mock<ISystemMessageService> _systemMessageServiceMock;
        private Mock<IHostSettingManager> _hostSettingManager;

        public AccountRegistrationManagerTest()
        {
            _validationServiceMock = new Mock<IValidationService>();
            _userAccountRepoMock = new Mock<IUserAccountRepo>();
            _stringGeneratorMock = new Mock<IStringGenerator>();
            _emailSenderMock = new Mock<IEmailSender>();
            _hashUtilityMock = new Mock<IHashUtility>();
            _systemMessageServiceMock = new Mock<ISystemMessageService>();
        }

        [TestInitialize]
        public void Setup()
        {         
        }

        [TestMethod]
        public void ValidateAccountRegistrationInfo_ShouldHaveEmailAsTheInvalidField_WhenEmailPassedInIsEmpty()
        {
            // setup
            AccountRegistrationInfo acctRegistrationInfo = new AccountRegistrationInfo { Email = string.Empty, ConfirmPassword = string.Empty, Password = string.Empty, Username = string.Empty };
            _underTest = new AccountRegistrationManager(_validationServiceMock.Object, _userAccountRepoMock.Object, _stringGeneratorMock.Object,
                _emailSenderMock.Object, _hashUtilityMock.Object, _systemMessageServiceMock.Object, _hostSettingManager.Object);

            // run
            ICollection<Tuple<UserAccountField, string>> invalidFieldsAndError = new List<Tuple<UserAccountField, string>>();
            _underTest.ValidateAccountRegistrationInfo(acctRegistrationInfo, invalidFieldsAndError);

            // verify
            Assert.IsTrue(invalidFieldsAndError.Single(p => p.Item1 == UserAccountField.Email) != null);
        }

        [TestMethod]
        public void ValidateAccountRegistrationInfo_ShouldHaveEmailAsTheInvalidField_WhenEmailPassedInIsInvalidFormat()
        {
            // setup
            AccountRegistrationInfo acctRegistrationInfo = new AccountRegistrationInfo { Email = "A@b@c@example.com", ConfirmPassword = string.Empty, Password = string.Empty, Username = string.Empty };
            _underTest = new AccountRegistrationManager(_validationServiceMock.Object, _userAccountRepoMock.Object, _stringGeneratorMock.Object,
                _emailSenderMock.Object, _hashUtilityMock.Object, _systemMessageServiceMock.Object, _hostSettingManager.Object);

            // run
            ICollection<Tuple<UserAccountField, string>> invalidFieldsAndError = new List<Tuple<UserAccountField, string>>();
            _underTest.ValidateAccountRegistrationInfo(acctRegistrationInfo, invalidFieldsAndError);

            // verify
            Assert.IsTrue(invalidFieldsAndError.Single(p => p.Item1 == UserAccountField.Email) != null);
        }

        //[TestMethod]
        //public void ValidateEmail_ShouldReturnEmailInUse_WhenEmailPassedInIsRegistered()
        //{
        //    // setup
        //    const string inUseEmail = "inuse@example.com";
        //    AccountRegistrationInfo acctRegistrationInfo = new AccountRegistrationInfo { Email = inUseEmail, ConfirmPassword = string.Empty, Password = string.Empty, Username = string.Empty };
        //    _userAccountRepoMock.Setup(p => p.GetUserIdByEmailAddress(inUseEmail)).Returns(1);
        //    _validationServiceMock.Setup(p => p.ValidateEmailAddress(inUseEmail)).Returns(true);

        //    _underTest = new AccountRegistrationManager(_validationServiceMock.Object, _userAccountRepoMock.Object, _stringGeneratorMock.Object,
        //        _emailSenderMock.Object, _hashUtilityMock.Object, _systemMessageServiceMock.Object, _hostSettingManager.Object);

        //    // run
        //    NewAccountRegistrationErrorEnum errorEnum;
        //    _underTest.ValidateEmail(inUseEmail, out errorEnum);

        //    // verify
        //    Assert.AreEqual(NewAccountRegistrationErrorEnum.EmailInUse, errorEnum);
        //}

        //[TestMethod]
        //public void ValidatePassword_ShouldReturnInvalidPassword_WhenPasswordIsEmpty()
        //{
        //    // setup
        //    _underTest = new AccountRegistrationManager(_validationServiceMock.Object, _userAccountRepoMock.Object, _stringGeneratorMock.Object,
        //        _emailSenderMock.Object, _hashUtilityMock.Object, _systemMessageServiceMock.Object);

        //    // run
        //    NewAccountRegistrationErrorEnum errorEnum;
        //    _underTest.ValidatePassword(string.Empty, out errorEnum);

        //    // verify
        //    Assert.AreEqual(NewAccountRegistrationErrorEnum.InvalidPassword, errorEnum);
        //}

        //[TestMethod]
        //public void ValidatePassword_ShouldReturnPasswordTooLong_WhenPasswordLengthIsGreaterThanMax()
        //{
        //    // setup
        //    const int passwordMaxLength = 7;
        //    const string tooLongPassword = "abcdefgh";
        //    _underTest = new AccountRegistrationManager(_validationServiceMock.Object, _userAccountRepoMock.Object, _stringGeneratorMock.Object,
        //        _emailSenderMock.Object, _hashUtilityMock.Object, _systemMessageServiceMock.Object);

        //    // run
        //    NewAccountRegistrationErrorEnum errorEnum;
        //    _underTest.ValidatePassword(tooLongPassword, 6, passwordMaxLength, out errorEnum);

        //    // verify
        //    Assert.AreEqual(NewAccountRegistrationErrorEnum.PasswordTooLong, errorEnum);
        //}

        //[TestMethod]
        //public void ValidatePassword_ShouldReturnTrue_WhenPasswordLengthEqualsMax()
        //{
        //    // setup
        //    const int passwordMaxLength = 7;
        //    const string validPassword = "abcdefg";
        //    _underTest = new AccountRegistrationManager(_validationServiceMock.Object, _userAccountRepoMock.Object, _stringGeneratorMock.Object,
        //        _emailSenderMock.Object, _hashUtilityMock.Object, _systemMessageServiceMock.Object);

        //    // run and verify
        //    NewAccountRegistrationErrorEnum errorEnum;
        //    Assert.IsTrue(_underTest.ValidatePassword(validPassword, 6, passwordMaxLength, out errorEnum));
        //}

        //[TestMethod]
        //public void ValidatePassword_ShouldReturnPasswordTooShort_WhenPasswordLengthLessThanMin()
        //{
        //    // setup
        //    const int passwordMinLength = 6;
        //    const string tooShortPassword = "abcde";
        //    _underTest = new AccountRegistrationManager(_validationServiceMock.Object, _userAccountRepoMock.Object, _stringGeneratorMock.Object,
        //        _emailSenderMock.Object, _hashUtilityMock.Object, _systemMessageServiceMock.Object);

        //    // run
        //    NewAccountRegistrationErrorEnum errorEnum;
        //    _underTest.ValidatePassword(tooShortPassword, passwordMinLength, 7, out errorEnum);

        //    // verify
        //    Assert.AreEqual(NewAccountRegistrationErrorEnum.PasswordTooShort, errorEnum);
        //}

        //[TestMethod]
        //public void ValidatePassword_ShouldReturnTrue_WhenPasswordLengthEqualsMin()
        //{
        //    // setup
        //    const int passwordMinLength = 6;
        //    const string tooShortPassword = "abcdef";
        //    _underTest = new AccountRegistrationManager(_validationServiceMock.Object, _userAccountRepoMock.Object, _stringGeneratorMock.Object,
        //        _emailSenderMock.Object, _hashUtilityMock.Object, _systemMessageServiceMock.Object);

        //    // run
        //    NewAccountRegistrationErrorEnum errorEnum;

        //    // verify
        //    Assert.IsTrue(_underTest.ValidatePassword(tooShortPassword, passwordMinLength, 7, out errorEnum));
        //    Assert.AreEqual(NewAccountRegistrationErrorEnum.None, errorEnum);
        //}
    }
}
